/**
 * Copyright (C) 2013-2014 the original author or authors.
 */
package com.foreveross.bsl.push.domain.entity;

import java.util.ArrayList;
import java.util.Collection;
import java.util.HashSet;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Set;

import org.apache.commons.lang3.StringUtils;
import org.springframework.util.Assert;

import com.google.common.collect.Lists;
import com.google.common.collect.Sets;

/**
 * 标签集合帮助类
 *
 * @author Wangyi
 * @version v1.0
 *
 * @date 2013-9-2
 *
 */
public class TagsHelper {
	
	private final Set<TagEntry> tags = Sets.newHashSet();
	
	/**
	 * 
	 */
	public TagsHelper() {
	}
	
	public TagsHelper(Collection<TagEntry> tags){
		if(tags!=null)
			this.setTags(tags);
	}
	
	public TagsHelper(Map<String, String> tags){
		if(tags!=null){
			Collection<TagEntry> tagList=new ArrayList<TagEntry>(tags.size());
			for(Map.Entry<String, String> entry : tags.entrySet()){
				tagList.add(safeEntry(entry));
			}
			this.setTags(tagList);
		}
	}
	
	public Set<TagEntry> getTags() {
		return Sets.newHashSet(this.tags);
	}
	
	public int getTagsCount(){
		return this.tags.size();
	}

	public void setTags(Collection<TagEntry> tags) {
		this.tags.clear();
		if(tags!=null){
			this.tags.addAll(processTagEntrys(tags));
		}
	}
	
	private Set<TagEntry> processTagEntrys(Collection<TagEntry> tags){
		//使用HashSet过虑重复的TagEntry
		Set<TagEntry> tes=new HashSet<TagEntry>();
		for(TagEntry tag : tags){
			tes.addAll(this.processTagEntry(tag));
		}
		return tes;
	}
	
	/**
	 * 处理有逗号分隔的标签值：将逗号分隔的标签值视为多个标签
	 * @param tag
	 * @return
	 */
	private Set<TagEntry> processTagEntry(TagEntry tag){
		Assert.notNull(tag);
		Assert.notNull(tag.getKey());
		Set<TagEntry> tes=new HashSet<TagEntry>();
		if(tag.getValue()==null || StringUtils.isEmpty(tag.getValue())){
			tes.add(tag);
			return tes;
		}
		//使用HashSet过虑重复的TagEntry
		String[] values=StringUtils.split(tag.getValue(), ',');
		if(values.length>1){
			for(String v : values){
				tes.add(new TagEntry(tag.getKey(), v));
			}
		}
		else if(values.length==1){
			tes.add(tag);
		}
		return tes;
	}

	public TagsHelper addTag(String key, String value) {
		Assert.notNull(key);
		Assert.notNull(value);
		this.tags.addAll(this.processTagEntry(new TagEntry(key, value)));
		return this;
	}
	
	public String[] getTagKeys(){
		Set<String> tagKeys=Sets.newHashSet();
		for(TagEntry te : this.tags){
			tagKeys.add(te.getKey());
		}
		return tagKeys.toArray(new String[0]);
	}
	
	public int getTagKeysCount(){
		return this.getTagKeys().length;
	}
	
	public String getTag(String key) {
		String[] values=this.getTags(key);
		return values.length>0 ? values[0] : null;
	}
	
	/**
	 * 获取指定key的标签，没有key的标签返回空数组
	 * @param key
	 * @return
	 */
	public String[] getTags(String key){
		List<String> tagValues=Lists.newArrayList();
		for(TagEntry te : this.tags){
			if(te.equalsKey(key)){
				tagValues.add(te.getValue());
			}
		}
		return tagValues.toArray(new String[0]);
	}
	
	public String getTagsUseCommaString(String key){
		String[] values=this.getTags(key);
		if(values.length>0){
			StringBuilder sb=new StringBuilder(values[0]);
			for(int i=1; i<values.length; i++){
				sb.append(',').append(values[i]);
			}
			return sb.toString();
		}
		return null;
	}

	public TagsHelper removeTag(String key) {
		Iterator<TagEntry> it=this.tags.iterator();
		while(it.hasNext()){
			TagEntry tag=it.next();
			if(tag.equalsKey(key)){
				it.remove();
			}
		}
		return this;
	}
	
	public TagsHelper updateTag(String key, String value){
		Assert.notNull(key, "key param can not be null");
		return this.updateTag(new TagEntry(key, value));
	}
	
	public TagsHelper updateTag(TagEntry tag){
		Assert.notNull(tag, "tag param can not be null");
		return this.updateTags(Lists.newArrayList(tag));
	}
	
	public TagsHelper updateTags(Map<String, String> tags){
		Assert.notNull(tags, "tags param can not be null");
		List<TagEntry> tagEntrys=Lists.newArrayList();
		for(Map.Entry<String, String> entry : tags.entrySet()){
			tagEntrys.add(safeEntry(entry));
		}
		return this.updateTags(tagEntrys);
	}
	
	private TagEntry safeEntry(Map.Entry<String, String> entry){
		//增强处理map的健壮性：由于Java的假泛型问题,即使你的方法声明了是Map<String,String>但实际调用时我可以传个任意类型的Map
		String key, value;
		if(entry.getKey() instanceof String){
			key=entry.getKey();
		}
		else{
			Object obj=entry.getKey();
			key=obj.toString();
		}
		if(entry.getValue() instanceof String){
			value=entry.getValue();
		}
		else{
			Object obj=entry.getValue();
			value=obj.toString();
		}
		return new TagEntry(key, value);
	}
	
	public TagsHelper updateTags(Collection<TagEntry> tags){
		Assert.notNull(tags, "tags param can not be null");
		Set<TagEntry> tts=processTagEntrys(tags);
		Set<TagEntry> removalTags=Sets.newHashSet();
		Iterator<TagEntry> tagsIt=tts.iterator();
		TagEntry tag=null;
		//把待删除的标签区分出来
		while(tagsIt.hasNext()){
			tag=tagsIt.next();
			//如果输入的tag的value为空，表示删除该tag
			if(StringUtils.isEmpty(tag.getValue())){
				removalTags.add(tag);
				tagsIt.remove();
			}
		}
		if(!removalTags.isEmpty()){
			//删除this.tags包含removalTags的标签
			tagsIt=this.tags.iterator();
			while(tagsIt.hasNext()){
				tag=tagsIt.next();
				for(TagEntry te : removalTags){
					if(tag.equalsKey(te.getKey())){
						tagsIt.remove();
					}
				}
			}
		}
		//删除this.tags中包含tts
		tagsIt=this.tags.iterator();
		while(tagsIt.hasNext()){
			tag=tagsIt.next();
			for(TagEntry te : tts){
				if(tag.equalsKey(te.getKey())){
					tagsIt.remove();
					break;
				}
			}
		}
		if(!tts.isEmpty()){
			//更新this.tags： 相同则覆盖，不同则增加
			for(TagEntry te : tts){
				this.tags.add(te);
			}
		}
		return this;
	}
	
	public TagsHelper clearTags(){
		this.tags.clear();
		return this;
	}
}
